VGA-Kurs - Part #1 An alle, die sich schon ein biįchen mit Pascal und Assembler auskennen, und nun unbedingt Spiele, Demos oder anderes in VGA coden m”chten! Hier ist der erste Teil von "T.C.P.'s Beginner's Guide To VGA Coding"(TM)! (Anmerkung fr alle erfahrenen Coder: Ihr mįt das hier natrlich nicht lesen, da ihr das sowieso schon alles wiįt, aber es kann ja nix schaden, gelle? Ach so: Falls ich irgendwas falsch mache, k”nnt ihr mich natrlich berichtigen, schlieįlich is ja nobody perfect!) Wenn meine Annahme stimmt, daį viele Leute so was lesen wollen, werde ich diese Serie fortsetzen, bekomme ich allerdings nicht gengend Resonanz, werde ich das Schreiben einstellen. Ich werde in den ersten Teilen die Grundlagen vermitteln und mich sp„ter, bei gengend Resonanz wie gesagt, auch fortgeschritteneren Teilen der VGA-Programmierung annehmen, wie Mode-X, Undokumentierte VGA-Funktionen, Sprites, HiRes-Coding etc. Na dann mal ran ans Eingemachte! Wer Pascal hat, hat vielleicht schon mal ein biįchen mit BGIs rumgecodet. Inzwischen gibt es zwar auch 256-Farben-BGIs aber trotzdem: Vergeįt es! Diese Dinger taugen vielleicht fr irgendwelche HiRes-Lame-O-Slow-Anwendungen, fr die man das Rad (sprich: SVGA-Routinen) nicht neu erfinden will, aber fr Spiele (geschweige denn Demos) - nej, nej, nej, da brauchts schon n' bisserl mehr. "Also, wie komme ich in den 256-Farben-VGA-Modus, ohne an BGIs auch nur einen Gedanken zu verschwenden?" werdet ihr jetzt fragen. Die Antwort ist absolut simpel: Inline Assembler! (šbrigens DAS Demo-Coder-Zauberwort schlechthin!) Hier also eine Prozedur zum Initialisieren des 256-Farben-Modus: procedure SetMCGAMode;assembler; asm mov ax,13h int 10h end; Wie ja wohl jeder sehen kann, l„dt diese Prozedur das AX-Reg mit 13h und ruft den VGA-Bios-Interrupt 10h auf. Die VGA-Karte weiį nun, daį sie in den Modus 13h (320x200 Pixel, 256 Farben) schalten soll. Was lernen wir daraus? Wir schreiben in AX den Video-Modus, den wir haben m”chten, callen den INT 10h und -baff!- befinden wir uns im gewnschten Modus. Die Nummer des Standard Textmodus ist brigens 3h. Hier eine kleine šbungsaufgabe fr zu Hause: Wie komme ich zurck in den Textmodus? Richtig! Wir ersetzen 13h durch 03h. Den INT 10h sollte man sich brigens gut merken, da er sp„ter sehr wichtig werden wird. So, sch”n und gut, ich bin im richtigen Modus, aber was jetzt? Beginnen wir mit der simpelsten Operation im Grafikmodus: Das Setzen eines Pixels! Zuerst einmal: Was hat ein Pixel fr Eigenschaften? 1. X-Koordinate (0-319), 2. Y-Koordinate (0-199), 3. Farbe (0-255). Moment mal! War da nicht die Rede von 320x200x256 und nicht 319x199x255? Tja, das ist so: Der Computer f„ngt nicht bei 1 an zu z„hlen wie die meisten von uns, sondern bei 0. Was also fr uns 1 Dose Coke ist, ist fr den Prozessor 0 Dose Coke. Was fr uns X-Koord 1 ist, ist fr den Compi X-Koord 0. Alles klar? Der erste Pixel in der obersten Zeile ist also fr den Rechner (0,0), der zweite (1,0), der dritte (2,0), usw. Und so wollen wir es hier in Zukunft auch halten. Wenn man jetzt also solange weiter macht, bis man bei Pixel (319,0) angekommen ist, geht man in die n„chste Zeile und nach links. Jetzt hat man Pixel (0,1). Das kann man immer weiter treiben, bis man bei Pixel (319,199) angekommen ist. Jetzt kennt man jeden Pixel pers”nlich und kann sie abends zum Essen einladen ;-). Wie ihr wahrscheinlich schon bemerkt habt, werden Pixel-Koordinaten folgendermaįen angegeben: (X-Wert,Y-Wert). Damit ihr es euch besser vorstellen k”nnt, hier noch einmal bildlich: X 0,0ÄÄÄÄÄÄÄÄÄÄ> 319,0 ³ : ³ : Y ³ : ³ : ³ : Vśśśśśśśśśśśś 0,199 319,199 Mit der Farbe verh„lt es sich genauso. Versucht dieses um 1 verschobene System zu verinnerlichen, weil ihr nicht drum herumkommen werdet. So, puh (Schweiį-von-der-Stirn-wisch), das h„tten wir, aber wie setze ich jetzt einen Pixel? Da hilft uns unser alter Freund, der INT 10h. (Anmerkung fr alle erfahrenen Coder: Keine Panik, wir werden auch noch die Variante kennenlernen, die ohne das Bios auskommt.) Hier also eine Prozedur, die einen Pixel an die gewnschte Stelle in der gewnschten Farbe setzt: procedure PutPixel(x,y:integer;col:byte);assembler; asm mov ah,0Ch mov al,col mov cx,x mov dx,y int 10h end; Will man also einen weiįen (Farbe 31) Pixel an (55,120) setzen ruft man die Prozedur mit PutPixel(55,120,31); auf. Dieser Befehl schreibt nun ins AH-Reg die Funktionsnummer, in AL die gewnschte Farbnummer, in CX und DX die X- und Y-Koords. Anschlieįend wird der INT 10h bemht, die Arbeit zu bernehmen. Nun sehen wir im unteren linken Viertel des Bildschirms einen weiįen Punkt (vorrausgesetzt, wir befinden uns im Modus 13h). Nun, dieses Wissen ”ffnet uns die Tore zu vielen kleinen Spielereien, die ihr euch jetzt zu Hause ausdenken k”nnt. Wir k”nnten zum Bleistift den gesamten Bildschirm mit Pixeln in beliebigen Farben zuknallen. program FillScreen; uses crt; var n1,n2 : integer; : : (Hier stehen die oben : besprochenen Prozeduren) : begin randomize; SetMCGAMode; for n1 := 0 to 319 do for n2 := 0 to 199 do PutPixel(n1,n2,random(256)); readkey; SetTextMode; end. Sch”n, nich? Jetzt haben wir einen zugemllerten Screen. Aber wie kriegen wir ihn wieder leer? Ist schlieįlich nicht sooo sch”n auf Dauer! Die ganz schlauen werden jetzt sagen: "Ist doch ganz einfach! Ich ersetze das "random(256)" durch "0"!" Tja, auch ne L”sung, aber so einfach wollen wirs uns nun auch nicht machen. Auįerdem w„re diese L”sung viel zu langsam, und damit so unbrauchbar wie ein MS-Produkt ;-). Also, hier die bessere (und schnellere) L”sung: procedure ClrVGA(col:byte); begin fillchar(mem[$A000:0],64000,col); end; Hier ausnahmsweise mal kein Assembler sondern ein Standard-Pascal-Befehl am Werk. Er fllt den Speicherbereich ab A000h:0 (64000 Byte, hier blendet die VGA ihren Bildschirmspeicher ein, 320 x 200 = 64000) mit der Farbnummer in "Col" auf. Ihr k”nnt den Screen also in jeder beliebigen Farbe l”schen, aber am gebr„uchlichsten ist wohl 0 (Schwarz). Jetzt wo wir schon etwas mehr bewandelt sind, k”nnen wir uns der Verfeinerung unseres Wissens widmen. Zum Beilpils: Warum ist unsere PutPixel-Prozedur so langsam? Ganz einfach: Sie benutzt das Bios! Wenn wir mit dieser Prozedur ein Spiel oder sogar ein Demo machen wollten, wrden wir wahrscheinlich nicht besonders weit kommen! Will man also wirklich geschwindigkeitsoptimiert coden, muį man meistens einen anderen, unbequemeren Weg als das VGA-Bios benutzen. In diesem Fall k”nnen wir die Prozedur erheblich beschleunigen, wenn wir die Pixel-Daten direkt in den Bildschirmspeicher schreiben. Erinnert ihr euch? Der Bildschirmspeicher im Modus 13h ist ein 64000(320x200)Byte groįer Speicherbereich an der Adresse A000h:0. In diesem Bereich stehen die Farbwerte s„mtlicher Pixel auf dem VGA-Screen. In den ersten 320 Byte stehen also die Farbwerte aller Pixel der ersten VGA-Zeile hintereinander. Die n„chsten 320 Byte beinhalten die Werte der n„chsten Zeile, usw. bis zum letzten Pixel, dessen Farbwert an Adresse A000h:63999 steht. Da wir dies nun wissen, k”nnen wir mit Hilfe der Formel Byte-Adresse = 320 x Y-Koord + X-Koord berechnen, welche Adresse welcher Pixel einnimmt. Hier also die optimierte PutPixel-Routine: procedure PutPixel(x,y:integer;col:byte); begin mem[$A000:320*y+x] := col; end; Wer diese Prozedur nun in unser "FillScreen"-Proggi einbaut, wird die erhebliche Geschwindigkeitssteigerung bemerken. Aber es geht noch schneller! Und zwar, indem man nie Prozedur in Assembler schreibt (War ja klar! ;-). Aber das berlasse ich euch fr zu Hause, schlieįlich sollt ihr auch mal selber was machen. Gebte Coder k”nnen bestimmt noch ein paar Clocks raushauen. So, das wars dann frs Erste von "T.C.P.'s Beginner's Guide To VGA Coding"(TM)! Ich hoffe, es hat euch was gebracht, und ich bekomme reichlich Feedback. Gebt auch eure Wnsche an, was ihr auf jeden Fall in einer der Ausgaben besprochen sehen wollt. Ich schreibe diesen Kurs gerne, aber nur wenn sich auch genug Leute dafr interessieren, sonst kann ich mir die Arbeit sparen! Also, schreibt was! [ This text copyright (c) 1995-96 Johannes Spohr. All rights reserved. ] [ Distributed exclusively through PC-Heimwerker, Verlag Thomas Eberle. ] [ ] [ No part of this document may be reproduced, transmitted, ] [ transcribed, stored in a retrieval system, or translated into any ] [ human or computer language, in any form or by any means; electronic, ] [ mechanical, magnetic, optical, chemical, manual or otherwise, ] [ without the expressed written permission of the author. ] [ ] [ The information contained in this text is believed to be correct. ] [ The text is subject to change without notice and does not represent ] [ a commitment on the part of the author. ] [ The author does not make a warranty of any kind with regard to this ] [ material, including, but not limited to, the implied warranties of ] [ merchantability and fitness for a particular purpose. The author ] [ shall not be liable for errors contained herein or for incidental or ] [ consequential damages in connection with the furnishing, performance ] [ or use of this material. ]